package pl.mchaniewski.ryneczek.services.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.mchaniewski.ryneczek.dao.QuotationDao;
import pl.mchaniewski.ryneczek.pojo.Index;
import pl.mchaniewski.ryneczek.pojo.Quotation;
import pl.mchaniewski.ryneczek.services.QuotationService;
import pl.mchaniewski.ryneczek.utilities.DateUtil;

@Service("quotationService")
public class QuotationServiceImpl implements QuotationService {
    private static final Logger logger = LoggerFactory
            .getLogger(QuotationServiceImpl.class);
    private QuotationDao quotationDao;

    private static final int CLEAN_UP_NUMBER_OF_DAYS = -3;

    @Autowired
    public void setQuotationDao(QuotationDao quotationDao) {
        this.quotationDao = quotationDao;
    }

    @Override
    public void remove(Quotation quotation) {
        try {
            quotationDao.remove(quotation);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());
        }
    }

    @Override
    public Quotation save(Quotation entity) {
        try {
            return quotationDao.save(entity);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    public List<Quotation> findLatest(boolean wasInLastUpdate) {
        try {
            List<Quotation> latest = quotationDao.findLatest(wasInLastUpdate);

            List<String> outOfSystemIndices = Arrays
                    .asList(Index.OUT_OF_SYSTEM_INDICES);
            for (Iterator<Quotation> it = latest.iterator(); it.hasNext();) {
                Set<Index> companyIndices = it.next().getCompany().getIndexes();

                for (Iterator<Index> itInner = companyIndices.iterator(); itInner
                        .hasNext();) {
                    String indexName = itInner.next().getName();

                    if (outOfSystemIndices.contains(indexName)) {
                        it.remove();
                    }
                }
            }

            return latest;
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    public Quotation findLatest(Integer companyid, boolean wasInLastUpdate) {
        List<Quotation> latest;
        try {
            latest = quotationDao.findLatest(companyid, wasInLastUpdate);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }

        if (latest == null || latest.size() == 0) {
            return null;
        }

        return latest.get(latest.size() - 1);
    }

    @Override
    public Quotation findLatestByDate(Integer companyid, Date date) {
        List<Quotation> latest;
        try {
            latest = quotationDao.findLatestByDate(companyid, date);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }

        if (latest == null || latest.size() == 0) {
            return null;
        }

        return latest.get(latest.size() - 1);
    }

    @Override
    public List<Quotation> findByDateAndCompanyId(Integer companyid, Date date) {
        try {
            return quotationDao.findByDateAndCompanyId(companyid, date);
        } catch (Exception ex) {
            logger.error("Exception: {}", ex.getMessage());

            return null;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cleanArchiveRecords() {
        List<Quotation> latestQuotation = findLatest(true);
        if (logger.isDebugEnabled()) {
            logger.debug(
                    "Grabbed latest quotation list. Number of records: {}",
                    latestQuotation.size());
        }

        Date now = DateUtil.getNow();
        for (int i = -1; i >= CLEAN_UP_NUMBER_OF_DAYS; --i) {
            Date nextDate = DateUtil.addDate(now, i, 0, 0);
            if (logger.isDebugEnabled()) {
                logger.debug("Day: {}", DateUtil.dateToString(nextDate));
            }

            for (Quotation q : latestQuotation) {
                Quotation latest = findLatestByDate(q.getCompany()
                        .getCompanyid(), nextDate);

                if (latest != null) {
                    List<Quotation> garbageQuotation = findByDateAndCompanyId(q
                            .getCompany().getCompanyid(), nextDate);

                    if (logger.isDebugEnabled()) {
                        logger.debug("Company {} has {} garbage quotations.", q
                                .getCompany().getCompanyid(), garbageQuotation
                                .size() - 1);
                    }

                    for (Quotation garbage : garbageQuotation) {
                        if (!garbage.getQuotationid().equals(
                                latest.getQuotationid())) {
                            remove(garbage);
                        }
                    }
                }
            }
        }
    }
}
